package pt.um.jspecput.lib.writer;

import static org.junit.Assert.*;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;

import javax.validation.constraints.Pattern;

import org.databene.benerator.anno.InvocationCount;
import org.databene.feed4junit.Feeder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(Feeder.class)
public class ClassWriterHelperTest {

    private static BufferedWriter writer;
    private static BufferedReader reader;
    private static File file = new File("temp");

    @Before
    public final void setUp() throws Exception {
        FileHandler.createFile(file);
        writer = new BufferedWriter(new FileWriter(file));
        reader = new BufferedReader(new FileReader(file));
    }

    @After
    public final void tearDown() throws Exception {
        reader.close();
        file.delete();
    }

    @Test
    public void testConstructor() {
        TestClassWriterHelper a = new TestClassWriterHelper() {
        };

        assertNotNull(a);
    }

    @Test
    @InvocationCount(10)
    public void testWritePackage(
            @Pattern(regexp = "[a-z\\.]*") String packageName) throws Exception {
        String expected = "package " + packageName + ";";

        ClassWriterHelper.writePackage(writer, packageName);
        writer.close();

        assertEquals(expected, reader.readLine());
    }

    @Test
    @InvocationCount(10)
    public void testWriteImport(
            @Pattern(regexp = "[a-z\\.]*[A-Z][A-Za-z0-9]*(\\.\\*)?") String importedClass)
            throws Exception {
        String expected = "import " + importedClass + ";";

        ClassWriterHelper.writeImport(writer, importedClass);
        writer.close();

        assertEquals(expected, reader.readLine());
    }

    @Test
    @InvocationCount(10)
    public void testWriteStaticImport(
            @Pattern(regexp = "[a-z\\.]*[A-Z][A-Za-z0-9]*(\\.\\*)?") String importedMethods)
            throws Exception {
        String expected = "import static " + importedMethods + ";";

        ClassWriterHelper.writeStaticImport(writer, importedMethods);
        writer.close();

        assertEquals(expected, reader.readLine());
    }

    @Test
    @InvocationCount(10)
    public void testOpenPublicClassDeclaration(
            @Pattern(regexp = "[A-Z][A-Za-z0-9]*") String className)
            throws Exception {
        String expected = "public class " + className + " {";

        ClassWriterHelper.openPublicClassDeclaration(writer, className);
        writer.close();

        assertEquals(expected, reader.readLine());
    }

    @Test
    @InvocationCount(10)
    public void testOpenPublicAbstractClassDeclaration(
            @Pattern(regexp = "[A-Z][A-Za-z0-9]*") String className)
            throws Exception {
        String expected = "public abstract class " + className + " {";

        ClassWriterHelper.openPublicAbstractClassDeclaration(writer, className);
        writer.close();

        assertEquals(expected, reader.readLine());
    }

    @Test
    @InvocationCount(10)
    public void testOpenPublicFinalClassDeclaration(
            @Pattern(regexp = "[A-Z][A-Za-z0-9]*") String className)
            throws Exception {
        String expected = "public final class " + className + " {";

        ClassWriterHelper.openPublicFinalClassDeclaration(writer, className);
        writer.close();

        assertEquals(expected, reader.readLine());
    }

    @Test
    @InvocationCount(10)
    public void testOpenClassDeclaration(
            @Pattern(regexp = "[A-Z][A-Za-z0-9]*") String className)
            throws Exception {
        String expected = "class " + className + " {";

        ClassWriterHelper.openClassDeclaration(writer, className);
        writer.close();

        assertEquals(expected, reader.readLine());
    }

    @Test
    @InvocationCount(10)
    public void testOpenAbstractClassDeclaration(
            @Pattern(regexp = "[A-Z][A-Za-z0-9]*") String className)
            throws Exception {
        String expected = "abstract class " + className + " {";

        ClassWriterHelper.openAbstractClassDeclaration(writer, className);
        writer.close();

        assertEquals(expected, reader.readLine());
    }

    @Test
    @InvocationCount(10)
    public void testOpenFinalClassDeclaration(
            @Pattern(regexp = "[A-Z][A-Za-z0-9]*") String className)
            throws Exception {
        String expected = "final class " + className + " {";

        ClassWriterHelper.openFinalClassDeclaration(writer, className);
        writer.close();

        assertEquals(expected, reader.readLine());
    }

    @Test
    public void testCloseClassDeclaration() throws Exception {
        ClassWriterHelper.closeClassDeclaration(writer);
        writer.close();

        assertEquals("}", reader.readLine());
    }
}
